package com.framework.myandroid.view

import android.app.Activity
import android.content.ContentUris
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.database.Cursor
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
import android.util.Log
import android.widget.ImageView
import androidx.annotation.NonNull
import androidx.annotation.Nullable
import com.framework.myandroid.utils.Constant
import okhttp3.*
import java.io.File
import java.io.IOException
import java.util.concurrent.TimeUnit

class UploadHelper {
    /**
     * 压缩bitmap尺寸
     */
    fun compressImageSizeAndLoadBitmap(
        imgpath: String?,
        imageView: ImageView?
    ): Bitmap {
        val newOpts = BitmapFactory.Options()
        newOpts.inJustDecodeBounds = true
        val bitmap: Bitmap
        newOpts.inJustDecodeBounds = false
        var oldWidth = newOpts.outWidth
        var oldHeight = newOpts.outHeight
        if (newOpts.outHeight > newOpts.outWidth) {
            oldWidth = newOpts.outHeight
            oldHeight = newOpts.outWidth
        }
        var scale = 1
        //		if (oldWidth / imageView.getWidth() > oldHeight / imageView.getHeight()) {
//			scale = oldWidth / imageView.getWidth();
//		} else {
//			scale = oldHeight / imageView.getHeight();
//		}
        if (scale <= 0) {
            scale = 1
        }
        newOpts.inSampleSize = scale
        newOpts.inPreferredConfig = Bitmap.Config.RGB_565
        bitmap = BitmapFactory.decodeFile(imgpath, newOpts)
        return bitmap
    }

    fun decodeSampledBitmapFromFile(
        pathName: String?,
        reqWidth: Int,
        reqHeight: Int
    ): Bitmap {
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeFile(pathName, options)
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
        options.inJustDecodeBounds = false
        val src = BitmapFactory.decodeFile(pathName, options)
        return createScaleBitmap(src, reqWidth, reqHeight, options.inSampleSize)
    }

    private fun calculateInSampleSize(
        options: BitmapFactory.Options,
        reqWidth: Int,
        reqHeight: Int
    ): Int {
        // 源图片的高度和宽度
        val height = options.outHeight
        val width = options.outWidth
        var inSampleSize = 1
        if (height > reqHeight || width > reqWidth) {
            val halfHeight = height / 2
            val halfWidth = width / 2
            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while (halfHeight / inSampleSize > reqHeight && halfWidth / inSampleSize > reqWidth) {
                inSampleSize *= 2
            }
        }
        return inSampleSize
    }

    private fun createScaleBitmap(
        @NonNull src: Bitmap,
        dstWidth: Int,
        dstHeight: Int,
        inSampleSize: Int
    ): Bitmap {
// 如果是放大图片，filter决定是否平滑，如果是缩小图片，filter无影响，我们这里是缩小图片，所以直接设置为false
        val dst = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, false)
        if (src != dst) { // 如果没有缩放，那么不回收
            src.recycle() // 释放Bitmap的native像素数组
        }
        return dst
    }

    //从本地相册选择照片上传
    fun selectImageFromStore(@NonNull context: Activity, requestCode: Int) {
        val intent = Intent(Intent.ACTION_GET_CONTENT)
        intent.type = "image/*"
        context.startActivityForResult(intent, requestCode)
    }

    //从本地相册选择视频上传
    fun selectVideoFromStore(@NonNull context: Activity, requestCode: Int) {
        val intent = Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
        context.startActivityForResult(intent, requestCode)
    }

    /**
     * 根据Uri获取图片绝对路径，解决Android4.4以上版本Uri转换
     */
    @Nullable
    fun getImageAbsolutePath(
        @Nullable context: Context?,
        @Nullable imageUri: Uri?
    ): String? {
        if (context == null || imageUri == null) {
            return null
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
            DocumentsContract.isDocumentUri(context, imageUri)
        ) {
            if (isExternalStorageDocument(imageUri)) {
                val docId = DocumentsContract.getDocumentId(imageUri)
                val split = docId.split(":").toTypedArray()
                val type = split[0]
                if ("primary".equals(type, ignoreCase = true)) {
                    return Environment.getExternalStorageDirectory()
                        .toString() + "/" + split[1]
                }
            } else if (isDownloadsDocument(imageUri)) {
                val id = DocumentsContract.getDocumentId(imageUri)
                val contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"),
                    java.lang.Long.valueOf(id)
                )
                return getDataColumn(context, contentUri, null, null)
            } else if (isMediaDocument(imageUri)) {
                val docId = DocumentsContract.getDocumentId(imageUri)
                val split = docId.split(":").toTypedArray()
                val type = split[0]
                var contentUri: Uri? = null
                if ("image" == type) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                } else if ("video" == type) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                } else if ("audio" == type) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
                }
                val selection = MediaStore.Images.Media._ID + "=?"
                val selectionArgs =
                    arrayOf(split[1])
                return getDataColumn(context, contentUri, selection, selectionArgs)
            }
        } // MediaStore (and general)
        else if ("content".equals(imageUri.scheme, ignoreCase = true)) {
            // Return the remote address
            return if (isGooglePhotosUri(imageUri)) {
                imageUri.lastPathSegment
            } else getDataColumn(context, imageUri, null, null)
        } else if ("file".equals(imageUri.scheme, ignoreCase = true)) {
            return imageUri.path
        }
        return null
    }

    fun selectImageFromCamera(
        @NonNull context: Activity,
        requestCode: Int,
        @Nullable saveImage: File?
    ) {
        var saveImage = saveImage
        if (saveImage == null) {
            Log.i(TAG, "Image file parameter is null.")
            saveImage = File(
                Environment.getExternalStorageDirectory(),
                System.currentTimeMillis().toString() + ".png"
            )
        }
        val currentapiVersion = Build.VERSION.SDK_INT
        Log.i(
            TAG,
            "---currentapiVersion===$currentapiVersion"
        )
        val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        if (currentapiVersion < Build.VERSION_CODES.N) {
            intent.action = MediaStore.ACTION_IMAGE_CAPTURE
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(saveImage))
            intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1)
        } else {
            if (saveImage.exists()) {
                try {
                    saveImage.createNewFile()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
            val contentValues = ContentValues()
            contentValues.put(MediaStore.Images.Media.DATA, saveImage.absolutePath)
            val uri = context.contentResolver
                .insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
        }
        context.startActivityForResult(intent, requestCode)
    }

    fun selectVideoFromCamera(
        @NonNull context: Activity,
        requestCode: Int,
        @Nullable saveVideo: File?
    ) {
        var saveVideo = saveVideo
        if (saveVideo == null) {
            Log.i(TAG, "Image file parameter is null.")
            saveVideo = File(
                Environment.getExternalStorageDirectory(),
                System.currentTimeMillis().toString() + ".mp4"
            )
        }
        val currentapiVersion = Build.VERSION.SDK_INT
        Log.i(
            TAG,
            "---currentapiVersion===$currentapiVersion"
        )
        val intent = Intent(MediaStore.ACTION_VIDEO_CAPTURE)
        if (currentapiVersion < Build.VERSION_CODES.N) {
            intent.action = MediaStore.ACTION_VIDEO_CAPTURE
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(saveVideo))
            intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1)
        } else {
            if (saveVideo.exists()) {
                try {
                    saveVideo.createNewFile()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
            val contentValues = ContentValues()
            contentValues.put(MediaStore.Images.Media.DATA, saveVideo.absolutePath)
            val uri = context.contentResolver
                .insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
        }
        context.startActivityForResult(intent, requestCode)
    }

    /**
     * 获取存储拍照图片的文件
     */
    @Nullable
    fun getCameraSaveFile(
        @NonNull context: Context,
        time: Long
    ): File {
        return if (Environment.MEDIA_MOUNTED == Environment.getExternalStorageState() || !Environment.isExternalStorageRemovable()) {
            File(context.externalCacheDir, "$time.png")
        } else {
            File(context.cacheDir, "$time.png")
        }
    }

    @Nullable
    fun getCameraSaveVideoFile(
        @NonNull context: Context,
        time: Long
    ): File {
        return if (Environment.MEDIA_MOUNTED == Environment.getExternalStorageState() || !Environment.isExternalStorageRemovable()) {
            File(context.externalCacheDir, "$time.mp4")
        } else {
            File(context.cacheDir, "$time.mp4")
        }
    }

    private fun getDataColumn(
        context: Context,
        @NonNull uri: Uri?,
        selection: String?,
        selectionArgs: Array<String>?
    ): String? {
        var cursor: Cursor? = null
        val column = MediaStore.Images.Media.DATA
        val projection = arrayOf(column)
        try {
            cursor =
                context.contentResolver.query(uri!!, projection, selection, selectionArgs, null)
            if (cursor != null && cursor.moveToFirst()) {
                val index = cursor.getColumnIndexOrThrow(column)
                return cursor.getString(index)
            }
        } finally {
            cursor?.close()
        }
        return null
    }

    fun isExternalStorageDocument(@NonNull uri: Uri): Boolean {
        return "com.android.externalstorage.documents" == uri.authority
    }

    fun isDownloadsDocument(@NonNull uri: Uri): Boolean {
        return "com.android.providers.downloads.documents" == uri.authority
    }

    fun isMediaDocument(@NonNull uri: Uri): Boolean {
        return "com.android.providers.media.documents" == uri.authority
    }

    fun isGooglePhotosUri(@NonNull uri: Uri): Boolean {
        return "com.google.android.apps.photos.content" == uri.authority
    }

    companion object {
        const val IMAGE_FROM_LOCAL = 111
        const val VIDEO_FROM_LOCAL = 222

        @NonNull
        private val TAG = "UploadHelper"
        private var uploadHelper: UploadHelper? = null

        @get:Synchronized
        val instance: UploadHelper?
            get() {
                if (uploadHelper == null) {
                    uploadHelper = UploadHelper()
                }
                return uploadHelper
            }

        fun uploadImage(
            files: List<File>,
            url: String?,
            callback: Callback?
        ) {
            if (files.size == 0) {
                return
            }
            val builder = MultipartBody.Builder().setType(MultipartBody.FORM)
            //        MultipartBody body = builder
//                .addFormDataPart("avatar_file", file.getName(), RequestBody.create(MediaType.parse("image/jpg"), file))
//                .addFormDataPart("avatar_file", file.getName(), RequestBody.create(MediaType.parse("image/jpg"), file))
//                .addFormDataPart("avatar_file", file.getName(), RequestBody.create(MediaType.parse("image/jpg"), file))
//                .addFormDataPart("avatar_file", file.getName(), RequestBody.create(MediaType.parse("image/jpg"), file))
//                .addFormDataPart("avatar_file", file.getName(), RequestBody.create(MediaType.parse("image/jpg"), file))
//                .addFormDataPart("avatar_file", file.getName(), RequestBody.create(MediaType.parse("image/jpg"), file))
//                .addFormDataPart("avatar_file", file.getName(), RequestBody.create(MediaType.parse("image/jpg"), file))
//                .addFormDataPart("avatar_file", file.getName(), RequestBody.create(MediaType.parse("image/jpg"), file))
//                .addFormDataPart("avatar_file", file.getName(), RequestBody.create(MediaType.parse("image/jpg"), file))
//                .addFormDataPart("avatar_file", file.getName(), RequestBody.create(MediaType.parse("image/jpg"), file))
//                .addFormDataPart("avatar_file", file.getName(), RequestBody.create(MediaType.parse("image/jpg"), file))
//                .addFormDataPart("avatar_file", file.getName(), RequestBody.create(MediaType.parse("image/jpg"), file))
//                .addFormDataPart("avatar_file", file.getName(), RequestBody.create(MediaType.parse("image/jpg"), file))
//                .build();
            for (file in files) {
                builder.addFormDataPart(
                    "avatar_file",
                    file.name,
                    RequestBody.create(MediaType.parse("image/jpg"), file)
                )
            }
            val request = Request.Builder().url(url)
                .post(builder.build())
                .addHeader(Constant.APP_TOKEN, SpHelper.instance.getToken())
                .build()
            OkHttpClient.Builder().readTimeout(60, TimeUnit.SECONDS).build()
                .newCall(request).enqueue(callback)
        }
    }
}
